#ifndef _TAGFS_H_
#define _TAGFS_H_

#include <stdint.h>
#include <string>
#include <cstdio>
#include <map>
#include <list>
#include <stack>
#include <queue>
#include <sys/stat.h>
#include <sys/statvfs.h>

#ifndef FUSE_USE_VERSION
#define FUSE_USE_VERSION 26
#endif
#include <fuse.h>

#include "tagfs_node.h"
#include "tagfs_map.h"
#include "tagfs_tagtree.h"

class TagFS
{
	public:
		bool init(FILE*);
		void destroy();

		int unlink(std::string);
		int fgetattr(std::string, struct stat*, struct fuse_file_info*);
		bool readdir(std::string, std::list<std::string>*, std::list<struct stat>*);
		int open(std::string, struct fuse_file_info*);
		int ftruncate(std::string, uint64_t, struct fuse_file_info*);
		int read(std::string, char*, uint64_t, uint64_t, struct fuse_file_info*);
		int write(std::string, const char*, uint64_t, uint64_t, struct fuse_file_info*);
		int release(std::string, struct fuse_file_info*);
		int utimens(std::string, const struct timespec tv[2]);
		int rename(std::string, std::string);
		int access(std::string path, int mode);
		int statfs(std::string path, struct statvfs* vfs);
		int getxattr(std::string, std::string, char*, size_t);
		int listxattr(std::string, char*, size_t);
		int setxattr(std::string, std::string, std::string, size_t, int);
		int removexattr(std::string, std::string);

	private:
		FILE* fs;
		std::list<uint64_t> openedFiles;

		std::queue<uint16_t> fifo;
		uint16_t fifopass;
		bool fifowait();

		TagFS_Node    fsNodes;
		TagFS_Map     fsMaps;
		TagFS_TagTree fsTagTree;

		void addTag(std::string, uint64_t);
		void getTags(std::list<std::string>*, uint64_t);
		void remTag(std::string, uint64_t);

		int sptag__getattr(std::string, std::string, struct stat*, struct fuse_file_info*);
		int sptag__open(std::string, std::string, struct fuse_file_info*);
		int sptag__read(std::string, std::string, char*, uint64_t, uint64_t, struct fuse_file_info*);
		int sptag__write(std::string, std::string, const char*, uint64_t, uint64_t, struct fuse_file_info*);
		int sptag__truncate(std::string, std::string, uint64_t, struct fuse_file_info*);
		int sptag__utimens(std::string, std::string, const struct timespec tv[2]);
		int sptag__unlink(std::string, std::string);
		int sptag__access(std::string, std::string, int mode);
};

#endif
